package dragon.core.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import dragon.core.exception.ExceptionHandler;

/**
 * 日期工具类
 */
public class DateUtils {

	public final static String yyyy = "yyyy";

	public final static String MM = "MM";

	public final static String dd = "dd";

	public final static String yyyy_MM_dd = "yyyy-MM-dd";

	public final static String yyyyMMdd = "yyyyMMdd";

	public final static String yyyy_MM = "yyyy-MM";

	public final static String yyyyMM = "yyyyMM";

	public final static String HH_mm_ss = "HH:mm:ss";

	public final static String HH_mm = "HH:mm";

	public final static String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";

	public final static String yyyyMMddHHmmss = "yyyyMMddHHmmss";

	public final static String yyyy_MM_dd_HH_mm = "yyyy-MM-dd HH:mm";

	public final static String yyyyMMddHHmm = "yyyyMMddHHmm";

	public final static String yyyy_MM_dd_HH_mm_ss_SSS = "yyyy-MM-dd HH:mm:ss.SSS";

	public final static String yyyyMMddHHmmssSSS = "yyyyMMddHHmmssSSS";

	/**
	 * 默认为yyyy-MM-dd的格式化
	 * 
	 * @param date
	 * @return
	 * @Fixed by luyz
	 */
	public static String format(Date date) throws ExceptionHandler {
		return format(date, yyyy_MM_dd);
	}

	/**
	 * 日期格式化－将<code>Date</code>类型的日期格式化为<code>String</code>型
	 * 
	 * @param date
	 *            待格式化的日期
	 * @param pattern
	 *            时间样式
	 * @return 一个被格式化了的<code>String</code>日期
	 */
	public static String format(Date date, String pattern) throws ExceptionHandler {
		if (date == null) {
			return "";
		} else {
			return getFormatter(pattern).format(date);
		}
	}

	/**
	 * 默认为yyyy-MM-dd格式的解析
	 * 
	 * @param strDate
	 * @return
	 * @throws ParseException
	 * @Fixed by luyz
	 */
	public static Date parse(String strDate) throws ExceptionHandler {
		return parse(strDate, yyyy_MM_dd);
	}

	/**
	 * 日期解析－将<code>String</code>类型的日期解析为<code>Date</code>型
	 * 
	 * @param strDate
	 *            待解析的日期字符串
	 * @param pattern
	 *            日期格式
	 * @ExceptionHandler ParseException 如果所给的字符串不能被解析成一个日期
	 * @return 一个被格式化了的<code>Date</code>日期
	 */
	public static Date parse(String strDate, String pattern) throws ExceptionHandler {
		try {
			return getFormatter(pattern).parse(strDate);
		} catch (ParseException e) {
			throw new ExceptionHandler(e);
		}
	}

	/**
	 * 获取日期(java.util.Date)
	 * 
	 * @return
	 */
	public static synchronized Date getCurrDate() {
		Calendar calendar = Calendar.getInstance();
		return calendar.getTime();
	}

	/**
	 * 获取指定毫秒数所表示的日期
	 * 
	 * @param millis
	 *            millis the new time in UTC milliseconds from the epoch.
	 * @return
	 */
	public static synchronized Date getDate(long millis) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(millis);
		return calendar.getTime();
	}

	/**
	 * 获取当前日期字符串
	 * 
	 * @return 一个包含年月日<code>String</code>型日期，yyyyMMdd
	 */
	public static String getCurrDateStr() throws ExceptionHandler {
		return format(getCurrDate(), yyyyMMdd);
	}

	/**
	 * 获取当前日期字符串
	 * 
	 * @return 一个包含年月日的<code>String</code>型日期，yyyy-MM-dd
	 */
	public static String getCurrDateStr_() throws ExceptionHandler {
		return format(getCurrDate(), yyyy_MM_dd);
	}

	/**
	 * 获取当前日期字符串
	 * 
	 * @return 一个包含年月<code>String</code>型日期，yyyyMM
	 */
	public static String getCurrDateStr0() throws ExceptionHandler {
		return format(getCurrDate(), yyyyMM);
	}

	/**
	 * 获取当前日期字符串
	 * 
	 * @return 一个包含年月<code>String</code>型日期，yyyy-MM
	 */
	public static String getCurrDateStr0_() throws ExceptionHandler {
		return format(getCurrDate(), yyyy_MM);
	}

	/**
	 * 获取当前时间字符串
	 * 
	 * @return 一个包含时分秒的<code>String</code>型时间，HH:mm:ss
	 */
	public static String getCurrTimeStr() throws ExceptionHandler {
		return format(getCurrDate(), HH_mm_ss);
	}

	/**
	 * 获取当前时间字符串
	 * 
	 * @return 一个包含时分的<code>String</code>型时间，HH:mm
	 */
	public static String getCurrHMStr() throws ExceptionHandler {
		return format(getCurrDate(), HH_mm);
	}

	/**
	 * 获取当前日期时间字符串，格式: yyyyMMddHHmmss
	 * 
	 * @return 一个包含年月日时分秒的<code>String</code>型日期。yyyyMMddHHmmss
	 */
	public static String getCurrDateTimeStr() throws ExceptionHandler {
		return format(getCurrDate(), yyyyMMddHHmmss);
	}

	/**
	 * 获取当前日期时间字符串，格式: yyyy-MM-dd HH:mm:ss
	 * 
	 * @return 一个包含年月日时分秒的<code>String</code>型日期时间字符串，格式：yyyy-MM-dd HH:mm:ss
	 */
	public static String getCurrDateTimeStr_() throws ExceptionHandler {
		return format(getCurrDate(), yyyy_MM_dd_HH_mm_ss);
	}

	/**
	 * 获取指定毫秒数所表示的日期时间字符串，样式: yyyy-MM-dd HH:mm:ss
	 * 
	 * @param millis
	 *            millis the new time in UTC milliseconds from the epoch.
	 * @return 一个包含年月日时分秒的<code>String</code>型日期时间字符串，格式：yyyy-MM-dd HH:mm:ss
	 */
	public static String getDateTimeStr_(long millis) throws ExceptionHandler {
		return format(getDate(millis), yyyy_MM_dd_HH_mm_ss);
	}

	/**
	 * 获取指定毫秒数所表示的日期时间字符串，样式: yyyyMMddHHmmss
	 * 
	 * @param millis
	 *            millis the new time in UTC milliseconds from the epoch.
	 * @return 一个包含年月日时分秒的<code>String</code>型日期时间字符串，格式：yyyyMMddHHmmss
	 */
	public static String getDateTimeStr(long millis) throws ExceptionHandler {
		return format(getDate(millis), yyyyMMddHHmmss);
	}

	/**
	 * 获取当前日期时间字符串，格式: yyyy-MM-dd HH:mm
	 * 
	 * @return 一个包含年月日时分的<code>String</code>型日期时间字符串，格式: yyyy-MM-dd HH:mm
	 */
	public static String getCurrDateTimeStr0_() throws ExceptionHandler {
		return format(getCurrDate(), yyyy_MM_dd_HH_mm);
	}

	/**
	 * 获取当前日期时间字符串，格式: yyyyMMddHHmm
	 * 
	 * @return 一个包含年月日时分的<code>String</code>型日期时间字符串，格式: yyyyMMddHHmm
	 */
	public static String getCurrDateTimeStr0() throws ExceptionHandler {
		return format(getCurrDate(), yyyyMMddHHmm);
	}

	/**
	 * 获取当前日期时间字符串，格式: yyyyMMddHHmmssSSS
	 * 
	 * @return 一个包含年月日时分秒毫秒的<code>String</code>型日期时间字符串，格式：yyyyMMddHHmmssSSS
	 */
	public static String getCurrDateTimeStr1() throws ExceptionHandler {
		return format(getCurrDate(), yyyyMMddHHmmssSSS);
	}

	/**
	 * 获取当前日期时间字符串，格式: yyyy-MM-dd HH:mm:ss.SSS
	 * 
	 * @return 一个包含年月日时分秒毫秒的<code>String</code>型日期时间字符串，格式：yyyy-MM-dd HH:mm:ss.SSS
	 */
	public static String getCurrDateTimeStr1_() throws ExceptionHandler {
		return format(getCurrDate(), yyyy_MM_dd_HH_mm_ss_SSS);
	}

	/**
	 * 获取当前年分 样式：yyyy
	 * 
	 * @return 当前年分
	 */
	public static String getYear() throws ExceptionHandler {
		return format(getCurrDate(), yyyy);
	}

	/**
	 * 获取当前月分 样式：MM
	 * 
	 * @return 当前月分
	 */
	public static String getMonth() throws ExceptionHandler {
		return format(getCurrDate(), MM);
	}

	/**
	 * 获取月份
	 * 
	 * @param date
	 *            基准日期
	 * @param intervals
	 *            间隔月数
	 * @return
	 * @throws ExceptionHandler
	 */
	public static Date getMonth(Date date, int intervals) throws ExceptionHandler {
		try {
			java.util.Calendar calendar = java.util.Calendar.getInstance();
			calendar.setTime(date);
			calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + intervals);
			return calendar.getTime();
		} catch (Exception e) {
			throw new ExceptionHandler(e);
		}
	}

	/**
	 * 获取当前日期号 样式：dd
	 * 
	 * @return 当前日期号
	 */
	public static String getDay() throws ExceptionHandler {
		return format(getCurrDate(), dd);
	}

	/**
	 * 判断当前时间是一年中的第几天
	 * 
	 * @return
	 * @throws ExceptionHandler
	 */
	public static int getDayOfYear() throws ExceptionHandler {
		try {
			java.util.Calendar calendar = java.util.Calendar.getInstance();
			calendar.setTime(new Date());
			return calendar.get(Calendar.DAY_OF_YEAR);
		} catch (Exception e) {
			throw new ExceptionHandler(e);
		}
	}

	/**
	 * 判断当前时间是一天中的第几个小时
	 * 
	 * @return
	 * @throws ExceptionHandler
	 */
	public static int getHourOfday() throws ExceptionHandler {
		try {
			java.util.Calendar calendar = java.util.Calendar.getInstance();
			calendar.setTime(new Date());
			return calendar.get(Calendar.HOUR_OF_DAY);
		} catch (Exception e) {
			throw new ExceptionHandler(e);
		}
	}

	/**
	 * 获取日期
	 * 
	 * @param date
	 *            基准日期
	 * @param intervals
	 *            相隔天数
	 * @return
	 * @throws ExceptionHandler
	 */
	public static Date getDay(Date date, int intervals) throws ExceptionHandler {
		try {
			java.util.Calendar calendar = java.util.Calendar.getInstance();
			calendar.setTime(date);
			calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) + intervals);
			return calendar.getTime();
		} catch (Exception e) {
			throw new ExceptionHandler(e);
		}
	}

	/**
	 * 获取一个简单的日期格式化对象
	 * 
	 * @return 一个简单的日期格式化对象
	 */
	public static SimpleDateFormat getFormatter(String parttern) {
		return new SimpleDateFormat(parttern);
	}

	/**
	 * 获取两个日期相差天数
	 * 
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static long getIntevalDays(String startDate, String endDate) {
		try {
			return getIntevalDays(parse(startDate, yyyy_MM_dd), parse(endDate, yyyy_MM_dd));
		} catch (ExceptionHandler ee) {
			return 0l;
		}
	}

	/**
	 * 得到两个时间相差的天数
	 * 
	 * @param startDate
	 *            开始日期
	 * @param endDate
	 *            结束日期
	 * @return
	 * @throws ExceptionHandler
	 */
	public static long getIntevalDays(Date startDate, Date endDate) throws ExceptionHandler {
		try {
			Calendar startCalendar = Calendar.getInstance();
			Calendar endCalendar = Calendar.getInstance();

			startCalendar.setTime(startDate);
			endCalendar.setTime(endDate);
			long diff = endCalendar.getTimeInMillis() - startCalendar.getTimeInMillis();

			return (diff / (1000 * 60 * 60 * 24));
		} catch (Exception e) {
			throw new ExceptionHandler(e);
		}
	}

	/**
	 * 得到两个时间相差的年数
	 * 
	 * @param startDate
	 *            开始日期
	 * @param endDate
	 *            结束日期
	 * @return
	 * @throws ExceptionHandler
	 */
	public static int getIntevalYears(Date startDate, Date endDate) throws ExceptionHandler {
		try {
			Calendar startCalendar = Calendar.getInstance();
			Calendar endCalendar = Calendar.getInstance();

			startCalendar.setTime(startDate);
			endCalendar.setTime(endDate);

			int a = startCalendar.get(Calendar.YEAR);
			int b = endCalendar.get(Calendar.YEAR);
			return b - a;
		} catch (Exception e) {
			throw new ExceptionHandler(e);
		}
	}

	/**
	 * 得到两个时间相差的小时数
	 * 
	 * @param startDate
	 *            开始日期
	 * @param endDate
	 *            结束日期
	 * @return
	 */
	public static double getIntevalHours(Date startDate, Date endDate) {
		try {
			java.util.Calendar startCalendar = java.util.Calendar.getInstance();
			java.util.Calendar endCalendar = java.util.Calendar.getInstance();

			startCalendar.setTime(startDate);
			endCalendar.setTime(endDate);
			long diff = endCalendar.getTimeInMillis() - startCalendar.getTimeInMillis();

			return ((double) diff / (1000 * 60 * 60));
		} catch (Exception ee) {
			return 0.0;
		}
	}

	/**
	 * 得到两个时间相差的分钟数
	 * 
	 * @param startDate
	 *            开始日期
	 * @param endDate
	 *            结束日期
	 * @return
	 */
	public static double getIntevalMinutes(Date startDate, Date endDate) {
		try {
			java.util.Calendar startCalendar = java.util.Calendar.getInstance();
			java.util.Calendar endCalendar = java.util.Calendar.getInstance();

			startCalendar.setTime(startDate);
			endCalendar.setTime(endDate);
			long diff = endCalendar.getTimeInMillis() - startCalendar.getTimeInMillis();

			return ((double) diff / (1000 * 60));
		} catch (Exception ee) {
			return 0.0;
		}
	}

	/**
	 * 获取当前日期所在月的第一天
	 * 
	 * @return
	 * @throws ExceptionHandler
	 */
	public static Date getFirstDayOfMonth() throws ExceptionHandler {
		return getFirstDayOfMonth(getCurrDate());
	}

	/**
	 * 获取指定日期所在月的第一天
	 * 
	 * @param current
	 * @return
	 */
	public static Date getFirstDayOfMonth(Date date) throws ExceptionHandler {
		try {
			Calendar c = Calendar.getInstance();
			c.setTime(date);
			c.set(Calendar.DATE, 1);// 设为当前月的第一天
			return c.getTime();
		} catch (Exception e) {
			throw new ExceptionHandler(e);
		}
	}

	/**
	 * 获取当前日期所在月的最后一天
	 * 
	 * @return
	 * @throws ExceptionHandler
	 */
	public static Date getLastDayOfMonth() throws ExceptionHandler {
		return getLastDayOfMonth(getCurrDate());
	}

	/**
	 * 获取指定日期所在月的最后一天
	 * 
	 * @param date
	 *            日期
	 * @return
	 * @throws ExceptionHandler
	 */
	public static Date getLastDayOfMonth(Date date) throws ExceptionHandler {
		try {
			Calendar c = Calendar.getInstance();
			c.setTime(date);
			c.set(Calendar.MONTH, c.get(Calendar.MONTH) + 1);// 当前月加1变为下一个月
			c.set(Calendar.DATE, 1);// 设为下一个月的第一天
			c.add(Calendar.DATE, -1);// 减一天，变为本月最后一天
			return c.getTime();
		} catch (Exception e) {
			throw new ExceptionHandler(e);
		}
	}

	/**
	 * 判断指定时间是否过期
	 * 
	 * @param datetime
	 *            日期时间字符串
	 * @param parttern
	 *            日期时间格式
	 * @return
	 * @throws ExceptionHandler
	 */
	public static boolean isOverdue(String datetime, String parttern) throws ExceptionHandler {
		return DateUtils.parse(datetime, parttern).before(DateUtils.getCurrDate());
	}

	/**
	 * 以友好的方式显示过去的时间
	 * 
	 * @param time
	 *            时间
	 * @return
	 */
	public static String friendlyTime(Date time) {
		// 计算时间差，单位：秒
		int ct = (int) ((System.currentTimeMillis() - time.getTime()) / 1000);
		if (ct < 3600) {
			return String.format("%d 分钟之前", ct / 60);
		}
		if (ct >= 3600 && ct < 86400) {
			return String.format("%d 小时之前", ct / 3600);
		}
		if (ct >= 86400 && ct < 2592000) { // 86400 * 30
			int day = ct / 86400;
			if (day > 1) {
				return String.format("%d 天之前", day);
			} else {
				return "昨天";
			}
		}
		if (ct >= 2592000 && ct < 31104000) { // 86400 * 30
			return String.format("%d 月之前", ct / 2592000);
		}

		return String.format("%d 年之前", ct / 31104000);

	}

	/**
	 * 以友好的方式显示过去的时间
	 * 
	 * @param yyyyMMddHHmmss
	 *            日期时间字符串
	 * @return
	 * @throws ExceptionHandler
	 */
	public static String friendlyTime(String yyyyMMddHHmmss) throws ExceptionHandler {
		return friendlyTime(DateUtils.parse(yyyyMMddHHmmss, DateUtils.yyyyMMddHHmmss));
	}

}
